#include "Database.h"

using namespace std;

Database::Database(char* filename)
{
	mDatabase = NULL;
	Open(filename);
}
Database::~Database()
{
	sqlite3_close(mDatabase);  
	delete mDatabase;
	mDatabase = 0;
}

bool Database::Open(char* filename)
{
	if(sqlite3_open(filename, &mDatabase) == SQLITE_OK)
		return true;
	return false;   
}

bool Database::Execute(string query)
{
	sqlite3_stmt *statement;
	vector<string> values;
	int answer = 0;
	bool result;
	
	// *** Converting std::string into char* *** //
	int size = query.length();
	char* sqlQuery = new char[size];
	for(int i = 0; i < size; i++)
	{
		sqlQuery[i] = query[i];
	}

	if(sqlite3_prepare_v2(mDatabase, sqlQuery, -1, &statement, 0) == SQLITE_OK)
	{
		answer = sqlite3_step(statement);
		result = (answer != SQLITE_ROW);
	}
	else
		result = false;

	sqlite3_finalize(statement);

	string error = sqlite3_errmsg(mDatabase);
	if(error != "not an error")
	{
		cout << "SQL error" << endl;
		cout << "Query:\"" << query << "\"" << endl;
		cout << "Error: " << error << endl;
	}
	return result;
}

vector<string> Database::GetColumnsName(string tableName)
{
	sqlite3_stmt *statement;
	vector<string> values;

	// *** Converting std::string into char* *** //
	string query = "SELECT * FROM " + tableName + ";";
	int size = query.length();
	char* sqlQuery = new char[size];
	for(int i = 0; i < size; i++)
	{
		sqlQuery[i] = query[i];
	}

	if(sqlite3_prepare_v2(mDatabase, sqlQuery, -1, &statement, 0) == SQLITE_OK)
	{
		int count = sqlite3_column_count(statement);
		for(int i = 0; i < count; i++)
		{
			values.push_back(sqlite3_column_name(statement, i));
		}
	}

	return values;
}

int Database::GetLastInsertedRowId()
{
	string rowId = GetOneShot("SELECT LAST_INSERT_ROWID();");
	return atoi(rowId.c_str());
}

vector<string> Database::GetLine(string query)
{
	sqlite3_stmt *statement;
	vector<string> values;

	// *** Converting std::string into char* *** //
	int size = query.length();
	char* sqlQuery = new char[size];
	for(int i = 0; i < size; i++)
	{
		sqlQuery[i] = query[i];
	}

	if(sqlite3_prepare_v2(mDatabase, sqlQuery, -1, &statement, 0) == SQLITE_OK)
	{
		int cols = sqlite3_column_count(statement);
		int result = 0;
		result = sqlite3_step(statement);
		if(result == SQLITE_ROW)
		{
			for(int col = 0; col < cols; col++)
			{
				string val;
				char *ptr = (char*)sqlite3_column_text(statement, col);
				if(ptr) val = ptr; else val = "";
				values.push_back(val);
			}
		}
		sqlite3_finalize(statement);
	}

	string error = sqlite3_errmsg(mDatabase);
	if(error != "not an error")
	{
		cout << "SQL error" << endl;
		cout << "Query:\"" << query << "\"" << endl;
		cout << "Error: " << error << endl;
	}

	return values; 
}

string Database::GetOneShot(string query)
{
	sqlite3_stmt *statement;
	string value;
	
	// *** Converting std::string into char* *** //
	int size = query.length();
	char* sqlQuery = new char[size];
	for(int i = 0; i < size; i++)
	{
		sqlQuery[i] = query[i];
	}

	if(sqlite3_prepare_v2(mDatabase, sqlQuery, -1, &statement, 0) == SQLITE_OK)
	{
		int cols = sqlite3_column_count(statement);
		int result = 0;
		result = sqlite3_step(statement);
		if(result == SQLITE_ROW)
		{
			string val;
			char *ptr = (char*)sqlite3_column_text(statement, 0);
			if(ptr) val = ptr; else val = "";
			value = val;
		}
		sqlite3_finalize(statement);
	}

	string error = sqlite3_errmsg(mDatabase);
	if(error != "not an error")
	{
		cout << "SQL error" << endl;
		cout << "Query:\"" << query << "\"" << endl;
		cout << "Error: " << error << endl;
	}

	return value;
}

vector<vector<string>> Database::Query(string query)
{
	sqlite3_stmt *statement;
	vector<vector<string> > results;

	try
	{
		// *** Converting std::string into char* *** //
		int size = query.length();
		char* sqlQuery = new char[size];
		for(int i = 0; i < size; i++)
		{
			sqlQuery[i] = query[i];
		}

		if(sqlite3_prepare_v2(mDatabase, sqlQuery, -1, &statement, 0) == SQLITE_OK)
		{
			int cols = sqlite3_column_count(statement);
			int result = 0;
			while(true)
			{
				result = sqlite3_step(statement);
			
				if(result == SQLITE_ROW)
				{
					vector<string> values;
					for(int col = 0; col < cols; col++)
					{
						values.push_back((char*)sqlite3_column_text(statement, col));
					}
					results.push_back(values);
				}
				else
					break;
			}
	   
			sqlite3_finalize(statement);
		}

		string error = sqlite3_errmsg(mDatabase);
		if(error != "not an error")
		{
			cout << "SQL error" << endl;
			cout << "Query:\"" << query << "\"" << endl;
			cout << "Error: " << error << endl;
		}

	}
	catch(std::string s)
	{
		std::cout << "Fatal SQL Error: " << s << std::endl;
		sqlite3_finalize(statement);
	}
	
	return results;  
}